#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <cctype>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <set>
#include <algorithm>
#include <map>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef long long unsigned ull;
typedef unsigned uint;

template <class T> inline T sqr(T x) { return x * x; }
template <class T> inline void updMin(T& a, const T& b) { if (b < a) a = b; }
template <class T> inline void updMax(T& a, const T& b) { if (b > a) a = b; }

const int MAXN = 6000;

struct Edge
{
	int from, to;
	int cap, flow;
	Edge(int f, int t, int c) : from(f), to(t), cap(c), flow(0) {}
};

vector< Edge > e;
vector< vector< int > > g;
int q[MAXN], ptr[MAXN], dist[MAXN];

int all_cnt;
int n, m, k, s, t;
int aa[MAXN], bb[MAXN];
vector< vector< pair< int, int > > > goes;

bool bfs(int from, int to, int scale)
{
	memset(dist, -1, all_cnt * sizeof(dist[0]));
	int qh = 0, qt = 0;
	q[qt++] = from;
	dist[from] = 0;
	while (qh < qt) {
		int cur = q[qh++];
		for (vector< int >::const_iterator it = g[cur].begin(); it != g[cur].end(); ++it) {
			int e_id = *it;
			int to_v = e[e_id].to;
			if (dist[to_v] == -1 && e[e_id].cap >= e[e_id].flow + scale) {
				dist[to_v] = dist[cur] + 1;
				q[qt++] = to_v;
			}
		}
	}
	return (dist[to] != -1);
}

int dfs(int v, int to, int flow)
{
	if (v == to || flow == 0) {
		return flow;
	}
	int cnt = int(g[v].size());
	for (int &cp = ptr[v]; cp < cnt; ++cp) {
		int e_id = g[v][cp];
		int to_v = e[e_id].to;
		if (dist[to_v] != dist[v] + 1) {
			continue;
		}
		int pushed = dfs(to_v, to, min(flow, e[e_id].cap - e[e_id].flow));
		if (pushed) {
			e[e_id].flow += pushed;
			e[e_id ^ 1].flow -= pushed;
			return pushed;
		}
	}
	return 0;
}

int dinic(int from, int to)
{
	int res = 0;
	for (int scale = 1 << 16; scale > 0; scale /= 2) {
		while (bfs(from, to, scale)) {
			memset(ptr, 0, all_cnt * sizeof(ptr[0]));
			int pushed = 0;
			while ((pushed = dfs(from, to, 1000000000))) {
				res += pushed;
			}
		}
	}
	return res;
}

void add_edge(int x, int y, int cap)
{
	g[x].push_back(e.size());
	e.push_back(Edge(x, y, cap));
	g[y].push_back(e.size());
	e.push_back(Edge(y, x, 0));
}

bool can_find(int val)
{
	all_cnt = n * (val + 1);
	int st_val = s * (val + 1), en_val = t * (val + 1) + val;
	e.clear();
	g.clear();
	g.resize(all_cnt);
	for (int ctm = 0; ctm < val; ++ctm) {
		for (int i = 0; i < n; ++i) {
			add_edge(i * (val + 1) + ctm, i * (val + 1) + ctm + 1, 2 * k);
		}
		for (int e_id = 0; e_id < m; ++e_id) {
			int u = aa[e_id], v = bb[e_id];
			add_edge(u * (val + 1) + ctm, v * (val + 1) + ctm + 1, 1);
			add_edge(v * (val + 1) + ctm, u * (val + 1) + ctm + 1, 1);
		}
	}
	return dinic(st_val, en_val) >= k;
}

void recover(int v, int to, int days, int cur_day, int id)
{
	if (v == to) {
		return;
	}
	for (vector< int >::const_iterator it = g[v].begin(); it != g[v].end(); ++it) {
		if (e[*it].flow > 0) {
			--e[*it].flow;
			int to_v = e[*it].to;
			if (v + 1 != to_v) {
				goes[cur_day].push_back(make_pair(id, to_v / (days + 1)));
			}
			recover(to_v, to, days, cur_day + 1, id);
			break;
		}
	}
}

int main()
{
	//freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout);
	scanf("%d%d%d%d%d", &n, &m, &k, &s, &t);
	--s, --t;
	for (int i = 0; i < m; ++i) {
		scanf("%d%d", &aa[i], &bb[i]);
		--aa[i], --bb[i];
	}
	int l = 0, r = n + k;
	while (l < r - 1) {
		int med = (l + r) / 2;
		if (can_find(med)) {
			r = med;
		} else {
			l = med;
		}
	}
	can_find(r);
	printf("%d\n", r);
	goes.assign(r, vector< pair< int, int > >());
	for (int i = 0; i < k; ++i) {
		recover(s * (r + 1), t * (r + 1) + r, r, 0, i);
	}
	for (int i = 0; i < r; ++i) {
		int cnt1 = int(goes[i].size());
		printf("%d", cnt1);
		for (int id = 0; id < cnt1; ++id) {
			printf(" %d %d", goes[i][id].first + 1, goes[i][id].second + 1);
		}
		printf("\n");
	}
	return 0;
}